package com.logictech.activity.system.interceptors;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.jeecgframework.p3.core.common.utils.DataDictTool;
import org.jeecgframework.p3.core.common.utils.StringUtil;
import org.jeecgframework.p3.core.logger.Logger;
import org.jeecgframework.p3.core.logger.LoggerFactory;
import org.jeecgframework.p3.core.utils.common.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.alibaba.fastjson.JSON;
import com.jeecg.p3.dict.entity.ProjectErrorConfig;
import com.logictech.activity.system.util.SignatureUtil;
import com.logictech.common.util.SystemEnum;

import net.sf.json.JSONObject;

public class SignInterceptor implements HandlerInterceptor {

	@Autowired
	private ResponseHolder responseHolder;

	public static final Logger logger = LoggerFactory.getLogger(SignInterceptor.class);
	private static final String SIGN_PARAM_NAME = "sign";
	private static final String SESSION_OPENID = "openid";
	private static final String SESSION_NICKNAME = "nickname";
	private List<String> excludeUrls;
	private String signKey;
	private String mode;

	public List<String> getExcludeUrls() {
		return this.excludeUrls;
	}

	public void setExcludeUrls(List<String> excludeUrls) {
		this.excludeUrls = excludeUrls;
	}

	public String getSignKey() {
		return this.signKey;
	}

	public void setSignKey(String signKey) {
		this.signKey = signKey;
	}

	public String getMode() {
		return this.mode;
	}

	public void setMode(String mode) {
		this.mode = mode;
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object object,
			Exception exception) throws Exception {

	}

	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object object,
			ModelAndView modelAndView) throws Exception {
	}

	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
		if ("DEV".equals(this.mode)) {
			return true;
		}
		Map paramMap = null;
		String sign = null;
		String openid = null;
		if (request.getMethod().equals("POST")) {
			paramMap = getPostSignMap(request);
			sign = paramMap.get("sign").toString();
			openid = paramMap.get("openId").toString();
		}else{
			sign = request.getParameter("sign");
			openid = request.getParameter("openId");
		}

		String requestPath = getRequestPath(request);
		String requestUrl = getRequestUrl(request);
		String basePath = request.getContextPath();
		// request.setAttribute("basePath", basePath);

		if (this.excludeUrls.contains(requestPath)) {
			return true;
		}
		if ((requestPath != null)) {
			if ((requestPath != null) && (requestPath.indexOf("/back/") > -1)) {
				return true;
			}
			if (requestUrl != null && StringUtil.notEmpty(sign)) {
				request.getSession().setAttribute("openId", openid);
				boolean check = SignatureUtil.checkSign(paramMap, this.signKey, sign);
				if (check) {
					//request.getRequestDispatcher(basePath + "/" + requestPath).forward(request, response);
					 response.sendRedirect(getRedirectUrl(basePath + "/" + requestPath, paramMap));
					return true;
				}
			} else {
				String session_openid = (String) request.getSession().getAttribute("openId");
				if (StringUtil.notEmpty(session_openid)) {
					if (StringUtil.notEmpty(openid)) {
						if (session_openid.equals(openid))
							return true;
					} else {
						return true;
					}
				}
			}

			responseHolder.setErrorMsg(SystemEnum.SIGN_ERROR);
			String json = JSON.toJSONString(responseHolder.getModel());
			this.returnJson(response, json);
			responseHolder.clean();
			return false;
		}
		return true;
	}

	public static Map parseToMap(String s) {
		Map map = new HashMap();
		JSONObject json = JSONObject.fromObject(s);
		Iterator keys = json.keys();
		while (keys.hasNext()) {
			String key = (String) keys.next();
			String value = json.get(key).toString();
			if (value.startsWith("{") && value.endsWith("}")) {
				map.put(key, parseToMap(value));
			} else {
				map.put(key, value);
			}

		}
		return map;
	}

	private void returnJson(HttpServletResponse response, String json) throws Exception {
		PrintWriter writer = null;
		response.setCharacterEncoding("UTF-8");
		response.setContentType("text/html; charset=utf-8");
		try {
			writer = response.getWriter();
			writer.print(json);

		} catch (IOException e) {
			logger.error("response error", e);
		} finally {
			if (writer != null)
				writer.close();
		}
	}

	/**
	 * post提交获取参数
	 * 
	 * @param request
	 * @return
	 * @throws IOException
	 */
	private Map<String, String> getPostSignMap(HttpServletRequest request) throws IOException {
		ServletRequest requestWrapper = new BodyReaderHttpServletRequestWrapper(request);
		String body = HttpHelper.getBodyString(requestWrapper);
		String param = null;
		try {
			param = URLDecoder.decode(body, "utf-8");
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		Map<String, String> paramMap = parseToMap(param);
		return paramMap;
	}

	/**
	 * get提交获取参数
	 * 
	 * @param request
	 * @return
	 */
	private Map<String, String> getSignMap(HttpServletRequest request) {
		Map paramMap = new HashMap();
		Map map = request.getParameterMap();
		Set es = map.entrySet();
		Iterator it = es.iterator();
		while (it.hasNext()) {
			Map.Entry entry = (Map.Entry) it.next();
			String k = (String) entry.getKey();
			Object ov = entry.getValue();
			String v = "";
			if ((ov instanceof String[])) {
				String[] value = (String[]) ov;
				v = value[0];
			} else {
				v = ov.toString();
			}
			paramMap.put(k, v);
		}
		return paramMap;
	}

	private String getRedirectUrl(String requestPath, Map<String, String> paramMap) {
		Set es = paramMap.entrySet();
		Iterator it = es.iterator();
		StringBuffer sb = new StringBuffer();
		sb.append(requestPath + "?");
		while (it.hasNext()) {
			Map.Entry entry = (Map.Entry) it.next();
			String k = (String) entry.getKey();
			String v = (String) entry.getValue();
			if ((v != null) && (!"".equals(v)) && (!"null".equals(v)) && (!"sign".equals(k)) && (!"nickname".equals(k))
					&& (!"key".equals(k))) {
				sb.append(k + "=" + v + "&");
			}
		}
		String redirectUrl = sb.toString();
		redirectUrl = redirectUrl.substring(0, redirectUrl.length() - 1);
		logger.info("---------------redirectUrl--------------" + redirectUrl);
		return redirectUrl;
	}

	private String getRequestPath(HttpServletRequest request) {
		String requestPath = request.getRequestURI();
		requestPath = requestPath.substring(request.getContextPath().length() + 1);
		return requestPath;
	}

	private String getRequestUrl(HttpServletRequest request) {
		String param = request.getQueryString();
		String requestUrl = request.getRequestURI();
		if (param != null) {
			requestUrl = requestUrl + "?" + request.getQueryString();
		}
		if (requestUrl.indexOf("#") != -1) {
			requestUrl = requestUrl.substring(0, requestUrl.indexOf("#"));
		}
		return requestUrl;
	}

	private String getProjectPath(String requestPath) {
		String projectPath = "";
		if (StringUtils.isNotEmpty(requestPath)) {
			requestPath.replace("\\", "/");
			int index = requestPath.lastIndexOf("/");
			if (index != -1) {
				projectPath = requestPath.substring(0, index);
				logger.info("---------------projectPath--------------" + projectPath);
			}
		}
		return projectPath;
	}

	private void redirectUrl404(String requestPath, String defaultUrl, HttpServletResponse response)
			throws IOException {
		String projectPath = getProjectPath(requestPath);
		try {
			if (StringUtils.isNotEmpty(projectPath)) {
				DataDictTool tool = new DataDictTool();
				ProjectErrorConfig config = tool.getSysErrorConfig(projectPath);
				String url = defaultUrl;
				if ((config != null) && (StringUtils.isNotEmpty(config.getRedirectUrl()))) {
					url = config.getRedirectUrl();
				}

				logger.info("---------------redirectUrl404--------------" + url);
				response.sendRedirect(url);
			}
		} catch (Exception e) {
			e.printStackTrace();
			logger.info("---------------redirectUrl404----异常----------" + defaultUrl);
			response.sendRedirect(defaultUrl);
		}
	}
}
